﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
using WalkingTec.Mvvm.Core.Extensions;
using System.Linq;
using System.Collections.Generic;
using TyMES.Model.BaseInformation;
using TyMES.ViewModel.BaseInformation.StationVMs;
using TyMES.Model;
using TyMES.Services;
using NPOI.OpenXmlFormats.Dml;
using TyMES.PassStationCommunication;
using TyMES.Model.Record;
using TyMES.Record.Controllers;
using Microsoft.AspNetCore.SignalR;
using TyMES.MidWare;
using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using TyMES.Communication;
using TyMES.TemporaryClass;
using Org.BouncyCastle.Asn1.Cmp;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Aliyun.OSS;
using TyMES.Communication.Request;
using System.Text.RegularExpressions;
using static TyMES.Record.Controllers.ProduceDataRecordController;
using Microsoft.AspNetCore.Http.HttpResults;
using Elsa.Models;
using Microsoft.Extensions.Logging;
using TyMES.Communication.Response;
using static TyMES.Communication.Request.RepairRequest;
using TyMES.ViewModel.Record.RepairRecordVMs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore.Storage;

namespace TyMES.BaseInformation.Controllers
{
    [AuthorizeJwtWithCookie]
    [ActionDescription("_Model.Station")]
    [ApiController]
    [Route("/api/BaseInformation/Station")]
    public partial class StationController : BaseApiController
    {
        
        private readonly OrderService orderService;
        private readonly IConfiguration configuration;
        private readonly PassStationService passStationService;
        private readonly TrayService trayService;
        private readonly IHubContext<NotificationHub> notification;
        private readonly IHubContext<InverseControlHub> inverseControl;
        private string _LineCode;
        private string factoryCode;
        //private readonly IServiceScope _serviceScope;
        //private readonly WTMContext _context;
        private NormalPassStationDomain _normalPassStationDomain;
        private readonly ILogger logger;
        private readonly PrintBarcodeService barcodeService;
        private readonly GlueDurationInspectionService glueDurationInspectionService;

        public StationController(OrderService orderService, IConfiguration configuration, PassStationService passStationService,
            TrayService trayService, IHubContext<NotificationHub> notificationHub, IHubContext<InverseControlHub> inverseControl,
             NormalPassStationDomain normalPassStationDomain, ILogger<StationController> logger,PrintBarcodeService barcodeService,
             GlueDurationInspectionService glueDurationInspectionService)
        {
            this.configuration = configuration;
            this.orderService = orderService;
            this.passStationService = passStationService;
            this.trayService = trayService;
            this.notification = notificationHub;
            this.inverseControl = inverseControl;
            //_serviceScope = serviceScopeFactory.CreateScope();
            //var sp = _serviceScope.ServiceProvider;
            //this._context = _context;
            this._normalPassStationDomain = normalPassStationDomain;
            this._LineCode = configuration["LineCode"];
            this.factoryCode = configuration["FactoryCode"];
            this.logger = logger;
            this.barcodeService = barcodeService;
            this.glueDurationInspectionService = glueDurationInspectionService;
        }

        [ActionDescription("Sys.Get")]
        [HttpGet("{id}")]
        public IActionResult Get(string id)
        {
            var vm = Wtm.CreateVM<StationVM>(id);
            return Ok(vm);
        }

        [ActionDescription("Sys.Create")]
        [HttpPost("[action]")]
        public async Task<IActionResult> Create(StationVM vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoAddAsync();

                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }

        }

        [ActionDescription("Sys.Edit")]
        [HttpPut("[action]")]
        public async Task<IActionResult> Edit(StationVM vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoEditAsync(false);
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }


        [HttpPost("BatchEdit")]
        [ActionDescription("Sys.BatchEdit")]
        public ActionResult BatchEdit(StationBatchVM vm)
        {
            if (!ModelState.IsValid || !vm.DoBatchEdit())
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                return Ok(vm.Ids.Count());
            }
        }

        [HttpPost("BatchDelete")]
        [ActionDescription("Sys.Delete")]
        public IActionResult BatchDelete(string[] ids)
        {
            var vm = Wtm.CreateVM<StationBatchVM>();
            if (ids != null && ids.Count() > 0)
            {
                vm.Ids = ids;
            }
            else
            {
                return Ok();
            }
            if (!ModelState.IsValid || !vm.DoBatchDelete())
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                return Ok(ids.Count());
            }
        }

        [ActionDescription("Sys.DownloadTemplate")]
        [HttpGet("GetExcelTemplate")]
        public IActionResult GetExcelTemplate()
        {
            var vm = Wtm.CreateVM<StationImportVM>();
            var qs = new Dictionary<string, string>();
            foreach (var item in Request.Query.Keys)
            {
                qs.Add(item, Request.Query[item]);
            }
            vm.SetParms(qs);
            var data = vm.GenerateTemplate(out string fileName);
            return File(data, "application/vnd.ms-excel", fileName);
        }

        [ActionDescription("Sys.Import")]
        [HttpPost("Import")]
        public ActionResult Import(StationImportVM vm)
        {

            if (vm.ErrorListVM.EntityList.Count > 0 || !vm.BatchSaveData())
            {
                return BadRequest(vm.GetErrorJson());
            }
            else
            {
                return Ok(vm.EntityList.Count);
            }
        }



        [NoLog]
        [HttpGet("GetLines")]
        public ActionResult GetLines()
        {
            return Ok(DC.Set<Line>().GetSelectListItems(Wtm, x => x.LineCode, x => x.LineCode.ToString()));
        }


        [HttpPost("[action]")]
        public ActionResult Select_GetLineByLineId(List<string> id)
        {
            var rv = DC.Set<Line>().CheckIDs(id).GetSelectListItems(Wtm, x => x.LineCode, x => x.LineCode.ToString());
            return Ok(rv);
        }


        [HttpPost("[action]")]
        public ActionResult Select_GetStationByLine(List<string> id)
        {
            var rv = DC.Set<Station>().CheckIDs(id, x => x.LineCodeId).GetSelectListItems(Wtm, x => x.StationCode, x => x.StationCode);
            return Ok(rv);
        }


        // 获取工位列表
        public record BasePara(string LineCode, string StationCode, string OrderCode, string SnNumber);
        [NoLog]
        [HttpPost("GetStationsByLine")]
        public ActionResult GetStationsByLine(BasePara para)
        {
            var rv1 = DC.Set<Station>().Where(e => e.LineCodeId == para.LineCode).ToList();
            //var rv2 = DC.Set<Order_Model>().Where(x => x.LineCode == para.LineCode && x.MOrderStatus == "3").ToList();
            return Ok(new {Stations = rv1});
        }


        // 扫码界面显示数据
        [NoLog]
        [HttpPost("GetUiInfo")]
        public async Task<ActionResult> GetUiInfo(BasePara para)
        {
            //节拍
            string Cycletime = "0";
            string GlueApplyCountDown = "0";

            //获取当前工位已入站sn信息 同时获取SN绑定的工单信息
            var virtualSn = passStationService.FindPassStationSN(para.LineCode, para.StationCode);

            if (virtualSn.Success == false) // 工位无工件信息，显示产线当前生产工单信息
            {
                Cycletime =await passStationService.GetStationCycleTime(para.LineCode, para.StationCode);
                //获取在生产工单
                var orderRes = orderService.GetOrderInProduct(para.LineCode, para.StationCode);
                if (orderRes.Success == false)
                {
                    return Ok(new { Code = "01", Mesg = orderRes.Mesg });
                }
                virtualSn.OrderCode = orderRes.Data.OrderCode;
                virtualSn.ScheduleCode = orderRes.Data.ScheduleCode;
                virtualSn.MaterialCode = orderRes.Data.MaterialCode;
                virtualSn.MaterialName = orderRes.Data.MaterialName;
            }
            else
            {
                //涂胶工位需要获取当前产品涂胶倒计时
                if (para.StationCode == "2-OP3250-0")
                {
                    var CountDownRes1 =await passStationService.GetGlueApplyCountDown("2-OP3230-0",180,virtualSn.SN);
                    //if (CountDownRes1.Success)
                        GlueApplyCountDown = CountDownRes1.Mesg;
                }

                if(para.StationCode == "2-OP3300-0")
                {
                    var CountDownRes2 = await passStationService.GetGlueApplyCountDown("2-OP3250-0",360, virtualSn.SN);
                    //if (CountDownRes2.Success)
                        GlueApplyCountDown = CountDownRes2.Mesg;
                }
            }

            //获取工单 产线 工位对应的出站数量
            var passStationCount = passStationService.GetPassStatonCount(virtualSn.OrderCode, virtualSn.ScheduleCode, para.LineCode, para.StationCode);
            if (passStationCount.Success == false) //获取出站数量失败
            {
                virtualSn.FinishedCount = -1;
                virtualSn.Desc = "获取工位出站数量失败";
            }
            else
            {
                virtualSn.FinishedCount = passStationCount.Data;
            }
            // 获取对应工单排程下工位对应的工序信息

            //string curOperationCode = passStationService.GetOperationCode(virtualSn.OrderCode, virtualSn.ScheduleCode, para.LineCode, para.StationCode);
            string curOperationCode = passStationService.ExstractOperation(para.StationCode);
     
            // 获取工单排程在该产线工位的装配信息
            List<ProductBOM> rv1 =await orderService.GetAssemblyInfo(virtualSn.OrderCode, virtualSn.ScheduleCode, para.LineCode, curOperationCode);
       
            // 获取SN在该产线 工位的已装配信息
            Dictionary<string, List<MaterialBindRecord>> rv2 = new Dictionary<string, List<MaterialBindRecord>>();
            if (virtualSn.Success == true)
            {
                rv2 = passStationService.BindingRelationship(virtualSn.SN, para.LineCode, para.StationCode);
            }
            // 判断装配完成情况
            foreach (var item in rv1)
            {
                var materiaclCode = item.AssemblyMaterialCode;
                string requiredCount = item.AssemblyConsumption;
                string hasAssemblied = "0";
                try
                {
                    hasAssemblied = rv2[materiaclCode].Count.ToString();
                }
                catch (Exception)
                {
                }
                if(requiredCount == hasAssemblied)
                {
                    item.AssemblyConsumption += "+";
                }
                else
                {
                    item.AssemblyConsumption += "-";
                }
            }

            var Logs = passStationService.GetStationLogs(para.LineCode, para.StationCode);
            var batchinfo = passStationService.GetBatchFlushUIs(para.LineCode, para.StationCode);   
            return Ok(new { Code = "00", Logs = Logs,Batchinfos = batchinfo, Materials = rv1, Bindings = rv2, Orders = new List<ResponseComSN>() { virtualSn }, Cycletime = Cycletime,GuleApplyCountDown = GlueApplyCountDown });
        }

        // 扫码物料绑定
        [HttpPost("HandleSnNumber")]
        public async Task<ActionResult> HandleSnNumber(BasePara para)
        {
            StationLogRecord stationLog = new StationLogRecord();
            stationLog.Date_Time = DateTime.Now;
            stationLog.CreateTime = DateTime.Now;
            stationLog.LineCode = para.LineCode;
            stationLog.StationCode = para.StationCode;
            // 上料接口处理
            //var res = trayService.LoadMaterial(para.SnNumber);
            /*
            if(res.Success == true) 
            {
                return Ok(new { Code = "00", Mesg = para.SnNumber + " 上料成功" });
            }
            */
            //生产物料绑定记录

            //校验是否进行电机扫码进站
            var checkpassMode = await passStationService.CheckScanPass(para.StationCode, para.SnNumber);
            if (checkpassMode.Success)
            {

                return
                Ok( await _normalPassStationDomain.ManualPassstation(para.SnNumber, para.StationCode, para.LineCode));
            }

            ResponseComSN getsn = passStationService.FindPassStationSN(para.LineCode, para.StationCode);
            if (getsn.Success == false)
            {
                stationLog.LogType = "bad";
                stationLog.Log = getsn.SN;
                DC.Set<StationLogRecord>().Add(stationLog);
                await DC.SaveChangesAsync();
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(para.LineCode, para.StationCode));
                TrayBVSNResponse trayBVSNResponse = new TrayBVSNResponse("",false,true,getsn.SN,getsn.SN, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                return Ok(trayBVSNResponse);
            }

            ParaAutoBindMaterial para1 = new ParaAutoBindMaterial(para.LineCode, para.StationCode, getsn.SN, para.SnNumber);
            TrayBVSNResponse res = new TrayBVSNResponse("000000", false, true, para.SnNumber, "", "");

            //上线工位的电机物料编码特殊保存用于后续校验
            if (para.StationCode == "2-OP3010-0" && (para.SnNumber == "16725791-00" || para.SnNumber == "16725789-00" || para.SnNumber == "16740221-00"))
            {
                var TZresult = await passStationService.SaveTZMaterialCodeAsPD(para1);
                
                return Ok(new TrayBVSNResponse("000000", false, true, para.SnNumber, "", ""));
            }

            
            if (!await PullOutMaterialAssemblySNs(para1))
                res = await AutoAdd(para1);
            if(res.success == true)
            {
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(para.LineCode, para.StationCode));
            }
            return Ok(res);
        }



        // 物料绑定
        [HttpPost("AutoAdd")]
        public async Task<TrayBVSNResponse> AutoAdd(ParaAutoBindMaterial para)
        {

            ApplicationRecord(para);
            try
            {
                // 查找sn入站信息
                var inStationInfo = await passStationService.FindInStationInfoAsync(para.SN, para.lineCode, para.stationCode);
                if (inStationInfo == null)
                {
                    await passStationService.stationlogadd3(_LineCode, para.stationCode, para.SN, "bad", para.SN + ",此sn无入站信息");

                    return new TrayBVSNResponse("000001", false, true, para.SN, "此sn无入站信息", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }

                // 获取工单排程在该产线工位的装配信息
                List<ProductBOM> boms = await orderService.GetAssemblyInfo(inStationInfo.OrderCode, inStationInfo.ScheduleCode, inStationInfo.LineCode, inStationInfo.OperationCode);
                if (boms.Count == 0)
                {
                    await passStationService.stationlogadd3(_LineCode, para.stationCode, para.SN, "bad", $"{para.SN} 在产线{para.lineCode}工位{para.stationCode} 无装配需求");


                    return new TrayBVSNResponse("000001", false, true, para.SN, para.lineCode + " " + para.stationCode + ": 该产线工位无装配需求", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }


                // 装配SN
                string[] AssemblyMaterialSN = para.AssemblyMaterialSNs.Split(",");
                List<MaterialBindRecord> records = new List<MaterialBindRecord>();
                
                // 生成对应物料绑定记录
                foreach (var item in AssemblyMaterialSN)
                {

                    ResponseComBase<MaterialBindRecord> itemRecord = await passStationService.CreateBindingRecord(item, boms, inStationInfo);


                    if (itemRecord.Success == false)
                    {
                        await passStationService.stationlogadd3(_LineCode, para.stationCode, para.SN, "bad", item + itemRecord.Mesg);

                        continue;
                    }

                    //校验此物料在本工位是否重复上传
                    if (!await passStationService.MaterialJudgeRepeat(itemRecord.Data))
                    {
                        await passStationService.stationlogadd3(_LineCode, para.stationCode, para.SN, "bad", $"物料{item }在工位{ para.stationCode}与{para.SN }重复绑定");
                        continue;
                    }

                    //校验物料是否已达目标用量
                    var isfilled = await passStationService.IsSingleMaterialFilled(itemRecord.Data,boms);
                    if (!isfilled.Success)
                    {
                        await passStationService.stationlogadd3(_LineCode, para.stationCode, para.SN, "bad", isfilled.Mesg);
                        continue;
                    }
                    else
                        records.Add(itemRecord.Data);
                }

                testrequest _testrequest = new testrequest(records);

                //信息全部筛掉直接返回
                if (_testrequest.records.Count == 0)
                {
                    await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(para.lineCode, para.stationCode));
                    return new TrayBVSNResponse("000001", false, true, para.SN, "物料校验失败，上传物料信息异常", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                //工厂MES物料绑定数据的上传
                bool uploadFlag = await _normalPassStationDomain.UploadMaterialBindInfo(_testrequest);

                foreach (var record in _testrequest.records)
                {
                    StationLogRecord stationLogRecord = new StationLogRecord();
                    var isFinishRecord = await passStationService.AddLocalBindingRecord(record, uploadFlag);
                    if (isFinishRecord.Success)
                        await passStationService.stationlogadd3(record.LineCode, record.StationCode, record.SnNumber, "good", record.AssemblyMaterialSn + "绑定到" + record.SnNumber + "本地保存成功");
                    else
                        await passStationService.stationlogadd3(record.LineCode, record.StationCode, record.SnNumber, "bad", record.AssemblyMaterialSn + "绑定到" + record.SnNumber + "本地保存失败");

                }
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(para.lineCode, para.stationCode));
                //校验物料是否全部上料完成，完成给scada信号返回
                if (await passStationService.MaterialVerification(para.SN, para.lineCode, inStationInfo.OperationCode, inStationInfo.StationCode,
                    inStationInfo.OrderCode, inStationInfo.ScheduleCode))
                {
                    //批次信息换绑
                    passStationService.ChangeBatchBindSN(para);

                    await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice(para.lineCode, para.stationCode, "2"));

                    //判断是否为选垫工位，选垫工位则触发其执行选垫
                    var PadSelectStation = DC.Set<CustomConfig>().Where(x => x.customProperty == "PadSelectStation").FirstOrDefault()?.propertyValue;
                    if (PadSelectStation == para.stationCode)
                    {

                        SelectPadResquest res = new SelectPadResquest
                        {
                            QXSN = para.AssemblyMaterialSNs,
                            stationCode = para.stationCode,
                            lineCode = para.lineCode,
                        };
                        //执行选垫
                        var autoSelectResult = await passStationService.AutoSelectPad(res, para.SN);
                        if (autoSelectResult.AutoSuccess)
                        {
                            //用signalR信号去触发前端查询选垫结果
                            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(autoSelectResult.QXAssmeblyCode, "PadSelectValue"));

                        }
                    }

                }
                return new TrayBVSNResponse("000000", true, false, para.SN, "success", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
            catch (Exception ex)
            {
                logger.LogInformation(ex.Message);
                await passStationService.stationlogadd3(_LineCode, para.stationCode,para.SN, "bad","物料绑定失败：" + para.SN + ex.Message);
                return new TrayBVSNResponse("000001", false, true, para.SN, ex.Message, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
        }
        // Helper methods would be defined here...

        

        /// <summary>
        /// 用于拉取转台扫码绑定的齿轴单体物料编码
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        public async Task<bool>  PullOutMaterialAssemblySNs(ParaAutoBindMaterial  record)
        {
            //StationLogRecord stationLog = new StationLogRecord();
            try
            {
                var boxmergStationCode = DC.Set<CustomConfig>().Where(x => x.customProperty == "boxmergStationCode" && x.propertyValue == record.stationCode).FirstOrDefault();
                if (boxmergStationCode == null)
                {
                   // await _normalPassStationDomain.stationlogadd(stationLog, record.LineCode, record.StationCode, record.SnNumber, "bad", "请先在自定义参数表预设轴系入箱工位");
                    return false;
                }
                
                string backSelectMaterialRegex = DC.Set<CustomConfig>().Where(x => x.customProperty == "backSelectMaterialRegex").FirstOrDefault().propertyValue;
                if (backSelectMaterialRegex == null)
                {
                    await passStationService.stationlogadd3( record.lineCode, record.stationCode, record.SN, "bad", "请先在自定义参数表预设轴系入箱主物料正则");
                    return false;
                }
                if (Regex.IsMatch(record.AssemblyMaterialSNs, backSelectMaterialRegex))
                {
                    string ScanBindMaterials = await  passStationService.ScanBindMaterialToSupple(record);
                    if (ScanBindMaterials != null)
                    {
                       
                            ParaAutoBindMaterial request = new ParaAutoBindMaterial(record.lineCode, record.stationCode, record.SN, ScanBindMaterials);
                            await AutoAdd(request);
                    }

                }
                return true;
            }
            catch (Exception ex)
            {
                await passStationService.stationlogadd3(record.lineCode, record.stationCode, record.SN, "bad", ex.Message);
                return true;
               
            }
            
        }

        
        public record testrequest(List<MaterialBindRecord> records);

        public void ApplicationRecord(ParaAutoBindMaterial para)
        {
            
            StationLogRecord stationLog1 = new StationLogRecord();
            stationLog1.Date_Time = DateTime.Now;
            stationLog1.CreateTime = stationLog1.Date_Time;
            stationLog1.LineCode = para.lineCode;
            stationLog1.StationCode = para.stationCode;
            stationLog1.LogType = "good";
            stationLog1.Log = $"SN:{para.SN} 申请绑定 {para.AssemblyMaterialSNs}";
            DC.Set<StationLogRecord>().Add(stationLog1);
            DC.SaveChanges();
        }

        //申请SN号
        [AllowAnonymous]
        [HttpPost("ApplyNewSN")]
        public async Task<ResponseBase> ApplyNewSN()
        {
            return new ResponseBase(false, "此电机未执行过返修处理");
        }

        //强制出站
        [HttpPost("ForcePassStation")]
        public async Task<TrayBVSNResponse> ForcePassStation(BasePara para)
        {

            StationLogRecord stationLog = new StationLogRecord();
            stationLog.Date_Time = DateTime.Now;
            stationLog.CreateTime = DateTime.Now;
            stationLog.LineCode = para.LineCode;
            stationLog.StationCode = para.StationCode;
            // 直接插入出站记录
            try
            {
                //目前强制进出站第一步就是要给个强制放的信号
                await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice(para.LineCode, para.StationCode,"1"));
                // 查找sn入站信息
                if (para.SnNumber == "" || para.SnNumber == null)
                {
                    stationLog.LogType = "bad";
                    stationLog.Log =  "强制进站sn为空，无法记录出站信息";
                    await DoAddStationStatusLog(stationLog);
                    return new TrayBVSNResponse("000002", false, true, para.SnNumber, "强制进站sn为空，无法记录出站信息", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                else
                {
                    var inStationInfo = await passStationService.FindInStationInfoAsync(para.SnNumber, para.LineCode, para.StationCode);
                    if (inStationInfo == null)
                    {
                        stationLog.LogType = "bad";
                        stationLog.Log = $"强制出站，sn{para.SnNumber}无进站信息";
                        await DoAddStationStatusLog(stationLog);
                        return new TrayBVSNResponse("000003", false, true, para.SnNumber, $"强制出站，sn{para.SnNumber}无进站信息", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    PassStationRecord outStationInfo = new PassStationRecord()
                    {
                        LineCode = inStationInfo.LineCode,
                        MaterialCode = inStationInfo.MaterialCode,
                        MaterialName = inStationInfo.MaterialName,
                        MaterialVersion = inStationInfo.MaterialVersion,
                        OperationCode = inStationInfo.OperationCode,
                        OrderCode = inStationInfo.OrderCode,
                        ScheduleCode = inStationInfo.ScheduleCode,
                        SnNumber = inStationInfo.SnNumber,
                        StationCode = inStationInfo.StationCode,
                        PassEndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        PassStatus = "pass",
                        ReqType = "2",
                        CreateTime = DateTime.Now,
                        Uploadflag=false
                        
                    };

                    PassStationRequestSup passStationRequestSup = new PassStationRequestSup()
                    {
                        operationCode = inStationInfo.OperationCode,
                        lineCode = inStationInfo.LineCode,
                        stationCode = inStationInfo.StationCode,
                        snNumber = inStationInfo.SnNumber,
                        orderCode = inStationInfo.OrderCode,
                        scheduleCode = inStationInfo.ScheduleCode,

                    };
                    await passStationService.BatchBindSN(passStationRequestSup);
                    await _normalPassStationDomain.ChangeBindOrder(passStationRequestSup);
                    DC.Set<PassStationRecord>().Add(outStationInfo);
                    //完成控制PLC操作

                    await DC.SaveChangesAsync();
                }
               
                
            }
            catch (Exception ex)
            {
                stationLog.LogType = "bad";
                stationLog.Log = para.SnNumber + "出站异常";
                await DoAddStationStatusLog(stationLog);
                return new TrayBVSNResponse("000001", false, true, para.SnNumber, "出站异常", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
            stationLog.LogType = "good";
            stationLog.Log = $"SN:{para.SnNumber}强制出站成功";
            await DoAddStationStatusLog(stationLog);
            return new TrayBVSNResponse("000000", true, false, para.SnNumber, $"SN:{para.SnNumber}强制出站成功", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }

        [ActionDescription("日志添加")]
        [HttpPost("DoAddStationStatusLog")]
        public async Task<bool> DoAddStationStatusLog(StationLogRecord stationLog)
        {
            stationLog.Date_Time = DateTime.Now;
            stationLog.CreateTime = DateTime.Now;
            DC.Set<StationLogRecord>().Add(stationLog);
            DC.SaveChanges();
            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(stationLog.LineCode, stationLog.StationCode));
            return true;
        }

        // NG出站
        [HttpPost("NGPassStation")]
        public Task<TrayBVSNResponse> NGPassStation(BasePara para)
        {
            // 保存不良信息
            try
            {

            }
            catch (Exception ex)
            {

            }

            //强制出站
            return ForcePassStation(para);
        }


        [ActionDescription("触发获取返修SN")]
        [HttpPost("PostNewSNtoScada")]
        public async Task<ResponseBase> PostNewSNtoScada(RepairRequest.request request)
        {
            StationLogRecord stationLog = new StationLogRecord();
            stationLog.LineCode = request.LineCode;
            stationLog.StationCode = request.StationCode;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            try
            {
                var repairRecord = DC.Set<RepairRecord>().Where(x=>x.TZMaterialCode==request.TZMaterialCode).FirstOrDefault();
                if (repairRecord == null)
                {
                    stationLog.LogType = "bad";
                    stationLog.Log = "此电机" + request.TZMaterialCode + "未执行过返修处理";
                    await DoAddStationStatusLog(stationLog);
                    return new ResponseBase(false, "此电机" + request.TZMaterialCode + "未执行过返修处理");
                }
                   
                await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice(repairRecord.CurrentSN, request.StationCode, "6"));
                stationLog.LogType = "good";
                stationLog.Log = "电机" + request.TZMaterialCode + "执行返修，新的返修SN为;"+repairRecord.CurrentSN;
                await DoAddStationStatusLog(stationLog);
                return new ResponseBase(true, repairRecord.CurrentSN);
            }
            catch (Exception ex)
            {
                stationLog.LogType = "bad";
                stationLog.Log = "电机" + request.TZMaterialCode + "执行返修失败：" + ex.Message;
                await DoAddStationStatusLog(stationLog);
                return new ResponseBase(false, "执行返修失败" + ex.Message);
            }
           
        }

        [ActionDescription("回流解绑")]
        [HttpPost("BackflowUnbind")]
        public async Task<ResponseBase> BackflowUnbind(RepairRequest.LooseMaterialRequest AllRepaiInfos)
        {
            try
            {
                if (AllRepaiInfos.SN == null||AllRepaiInfos.SN=="")
                    return new ResponseBase(false, "请先扫码获取电机绑定的发动机号");
                return await passStationService.LooseMaterialBindRecord(AllRepaiInfos);
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, "解绑失败"+ex.Message);
            }
        }

        [ActionDescription("物料上料")]
        [HttpPost("LoadMaterial")]
        public async Task<TrayBVSNResponse> LoadMaterial(UploadMT MT)
        {
            try
            {
                if(MT.inv=="")
                {
                    return new TrayBVSNResponse("000001", false, true, "", "上料失败,请先扫料码", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                UploadMaterial.uploadmaterialrequest request = new UploadMaterial.uploadmaterialrequest();
                request.stationCode =MT.stationCode;
                request.inv = MT.inv;
                if(await passStationService.uploadMaterialBatch(request))
                {
                    return new TrayBVSNResponse("000000", true, false, "", "上料成功", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                return new TrayBVSNResponse("000002", false, true, "", "上料失败", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));


            }
            catch (Exception ex)
            {
                return new TrayBVSNResponse("000002", false, true, "", "上料失败", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
        }

        [ActionDescription("漏产出补录")]
        [HttpPost("AddtionalRecord")]
        public async Task<TrayBVSNResponse> AddtionalRecord(AddtionalPassRecord para)
        {
            var responseSn = passStationService.FindVirtualSn(para.AssemblySn);
            if (responseSn.Success == false)
                return new TrayBVSNResponse("000001", false, true, "", "补漏产出失败"+responseSn.mesg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            var orderinfo = await passStationService.FindOrderInfo(responseSn.Sn);
            string stationCode = await passStationService.FindLastOP2StationCode(orderinfo.OrderCode);
            Postpara postpara = new Postpara(orderinfo,responseSn.Sn, stationCode);
            ResponseBase result =await passStationService.PostAddtionalPassStationRecord(postpara);
            
           if(result.Success == true)
                return new TrayBVSNResponse("000000", true, false, "", "补漏产出成功", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            return new TrayBVSNResponse("000002", false, true, "", "补漏产出失败", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }

        [ActionDescription("UI全检过站数据")]
        [HttpPost("FinishPass")]
        public async Task<UIResponse.FinishAllData> FinishPass(UIRequest.PassRecordUI res)
        {
            UIResponse.FinishAllData finishAllData = new UIResponse.FinishAllData();
            if(res.Type== "sn")
            {
                return await passStationService.GetAllFinishedataBySN(res);
            }
            if(res.Type== "assembly")
            {
                var materialdRecord = DC.Set<MaterialBindRecord>().Where(x=>x.AssemblyMaterialSn==res.SN).FirstOrDefault();
                if(materialdRecord == null)
                    return finishAllData;
                else
                {
                    res.SN= materialdRecord.SnNumber;
                    return await passStationService.GetAllFinishedataBySN(res);
                }

            }

            return finishAllData;
        }

        [ActionDescription("拧紧数据接收")]
        [HttpPost("UpdateTighteningData")]
        public async Task<TighteningResponse> UpdateTighteningData(TighteningRequest.ServerUpTable res)
        {
            //StationLogRecord stationLogRecord = new StationLogRecord();
            try
            {
               List<TighteningRequest.Tighten> tightendatas = JsonConvert.DeserializeObject<List<TighteningRequest.Tighten>>(res.dt);
               List <TighteningData> tighteningDatas =  await passStationService.MapToTighteningDatas(tightendatas);
               
               DC.Set<TighteningData>().AddRange(tighteningDatas);
               DC.SaveChanges();
               return new TighteningResponse(res.ChecKedID1, "OK", "");
            }
            catch (Exception ex)
            {
                logger.LogInformation("拧紧异常"+ex.Message);
                //await _normalPassStationDomain.stationlogadd(stationLogRecord,"DQ-TG-2","拧紧异常","","bad",ex.Message);
                return new TighteningResponse(res.ChecKedID1, "NG", "");
            }
        }

        [ActionDescription("生产工单看板数据")]
        [HttpGet("UIProductOrderPageInfo")]
        public async Task<UIResponse.ProductOrderUIInfo> UIProductOrderPageInfo()
        {
            UIResponse.ProductOrderUIInfo productOrderUIInfo = new UIResponse.ProductOrderUIInfo();
            productOrderUIInfo.date = new List<string>();
            productOrderUIInfo.weekQuantity = new List<int> ();
            productOrderUIInfo.weekPlan = new List<int>();
            productOrderUIInfo.stationDatas = new List<UIResponse.StationInfo>();
            try
            {
                productOrderUIInfo.date.AddRange(await passStationService.GetDate());
                productOrderUIInfo.weekQuantity.AddRange(await passStationService.GetProduceQuantity());
                productOrderUIInfo.weekPlan.AddRange(await passStationService.GetPlanEachWeek());
                productOrderUIInfo.currentWeekOutput = productOrderUIInfo.weekQuantity[productOrderUIInfo.weekQuantity.Count - 1].ToString();
                productOrderUIInfo.stationDatas.AddRange(await passStationService.GetStationInfos());
                var actualOutputAndPlan = await passStationService.GetOrderOutput();
                productOrderUIInfo.OrderOutput = actualOutputAndPlan.OrderOutput;
                productOrderUIInfo.OrderPlanQuantity = actualOutputAndPlan.OrderPlanQuantity;
            }
            catch (Exception ex)
            {

            }
            return productOrderUIInfo;
        }


        [AllRights]
        [ActionDescription("更改返修工位状态")]
        [HttpPost("ChangeRepairStationStatus")]
        public ResponseBase ChangeRepairStationStatus(RepairSTStatus repairSTStatus)
        {
            try
            {
                var RepairStatus = DC.Set<CustomConfig>().Where(x=>x.customProperty== repairSTStatus.configName).FirstOrDefault();
                if (RepairStatus != null)
                {
                    RepairStatus.propertyValue = repairSTStatus.status;
                    DC.SaveChanges();
                    return new ResponseBase(true, $"返修状态更新成功");
                }
                else
                    return new ResponseBase(false, $"返修状态更新异常：自定义参数表中未查询到BackUpStationStatus字段");

                
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"返修状态更新异常：{ex.Message}");
            }
        }


        public record testpara(string para);
        [HttpPost("Test1")]
        public async Task<string> Test1(testpara para)
        {
            //MaterialBindRecord record = new MaterialBindRecord();
            //record.LineCode = "DQ-TG-2";
            //record.StationCode = "2-OP3100-0";
            //record.AssemblyMaterialSn = "130378-12868403-00-20240803-1026";
            //record.SnNumber = "DM-TG-2R121300174";
            //UpdateInfo updateinfo = new UpdateInfo();
            ////updateinfo.updateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            //string data = JsonConvert.SerializeObject(updateinfo);
            //PullOutMaterialAssemblySNs( record);
            //await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice("DM-TG-2S040500095", "3WFD", "3"));
            //
            //

            //MaterialBindRecord materialBindRecord = new MaterialBindRecord();
            //materialBindRecord.SnNumber = "DM-TG-2R121600037";
            //materialBindRecord.AssemblyMaterialSn = "TZ220XYE 3G4126918";
            //materialBindRecord.OrderCode = "003100011594";
            //materialBindRecord.ScheduleCode = "PC241202001";
            //materialBindRecord.AssemblyMaterialCode = "16740221-00";
            //materialBindRecord.StationCode = "2-OP3010-0";
            //var res =await passStationService.IsSingleMaterialFilled(materialBindRecord);

            PassStationRequestSup passStationRequestSup = new PassStationRequestSup();
            passStationRequestSup.snNumber = para.para;
            passStationRequestSup.stationCode = "2-OP4010-0";
            passStationRequestSup.operationCode = "2-OP4010";


            //await passStationService.MaterialVerification
            //                    ("DM-TG-2S052000015", "DQ-TG-2", "2-OP4010",
            //                        "2-OP4010-0", "003100024205", "PC250513020");


            //var coderesult = await passStationService.MaterialInfoAsync();

            ResponseBase res = await _normalPassStationDomain.ChangeBindOrder(passStationRequestSup);


            return res.Mesg ;
        }

        /// <summary>
        /// 获取涂胶超时状态
        /// </summary>
        /// <returns></returns>
        [AllRights]
        [ActionDescription("获取涂胶超时状态")]
        [HttpGet("GetGlueTimeoutFlag")]
        public async Task<ResponseComBool> GetGlueTimeoutFlag()
        {
            return await glueDurationInspectionService.getGlueTimeoutFlag();
        }

        /// <summary>
        /// 重置涂胶超时状态
        /// </summary>
        /// <returns></returns>
        [AllRights]
        [ActionDescription("重置涂胶超时状态")]
        [HttpPost("ResetGlueTimeoutFlag")]
        public async Task<ResponseComBool> ResetGlueTimeoutFlag()
        {
            return await glueDurationInspectionService.updateGlueTimeoutFlag(false);
        }

    }
}